package com.fatri.lessionsimple.opengl.drawer

import android.content.Context
import android.opengl.GLES20
import android.opengl.Matrix
import com.fatri.lessionsimple.opengl.IDrawer
import com.fatri.lessionsimple.opengl.OpenGLTools
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer
import java.util.*

/**
 * 带相机变换矩阵的圆锥、圆柱
 */
class ConeDrawer(ctx: Context) : IDrawer(ctx) {


    private lateinit var vertexShaderCode  :String

    private val fragmentShaderCode = "precision mediump float;" +
            "varying vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}"

    private var mProgram = 0
    private lateinit var vertexBuffer: FloatBuffer


    val COORDS_PER_VERTEX = 3
    var triangleCoords: FloatArray? = null
    val radius = 1.0
    val height = 3.0f

    private var mPositionHandle = 0
    private var mColorHandle = 0


    //顶点个数
    private var vertexCount = 0

    //一个顶点占有的总字节数
    private val vertexStride = COORDS_PER_VERTEX * 4 // 每个顶点包括3个float，一个float四字节


    private val mViewMatrix = FloatArray(16)
    private val mProjectMatrix = FloatArray(16)
    private val mMVPMatrix = FloatArray(16)


    //设置颜色
    var color = floatArrayOf(
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f
    )
    lateinit var colorBuffer: FloatBuffer
    lateinit var indexBuffer: ShortBuffer


    lateinit var circleDrawer: CircleDrawer //底部圆
    override fun onSurfaceCreated() {
        GLES20.glEnable(GLES20.GL_DEPTH_TEST)


        triangleCoords = createPositions() //创建扇形顶点
        vertexCount = triangleCoords!!.size / COORDS_PER_VERTEX

        val bb = ByteBuffer.allocateDirect(triangleCoords!!.size * 4)
        bb.order(ByteOrder.nativeOrder())
        vertexBuffer = bb.asFloatBuffer()
        vertexBuffer.put(triangleCoords)
        vertexBuffer.position(0)


        //转换颜色着色器数据
        val cc = ByteBuffer.allocateDirect(color.size * 4)
        cc.order(ByteOrder.nativeOrder())
        colorBuffer = cc.asFloatBuffer()
        colorBuffer.put(color)
        colorBuffer.position(0)

        vertexShaderCode= OpenGLTools.readShaderCode(ctx,"cone/cone_vertex.glsl")
        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
        val fragShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)

        mProgram = GLES20.glCreateProgram()
        GLES20.glAttachShader(mProgram, vertexShader)
        GLES20.glAttachShader(mProgram, fragShader)
        GLES20.glLinkProgram(mProgram)

        circleDrawer= CircleDrawer(ctx)
        circleDrawer.onSurfaceCreated()
    }


    var n =360
    private fun createPositions(): FloatArray? {
        val data = ArrayList<Float>()
        data.add(0.0f) //设置圆心坐标
        data.add(0.0f)
        data.add(height)
        val angDegSpan: Float = 360f / n
        run {
            var i = 0f
            while (i < 360 + angDegSpan) {
                data.add((radius * Math.cos(i * Math.PI / 180f)).toFloat())
                data.add((radius * Math.sin(i * Math.PI / 180f)).toFloat())
                data.add(0f)
                i += angDegSpan
            }
        }
        val f = FloatArray(data.size)
        for (i in f.indices) {
            f[i] = data[i]
        }
        return f
    }

    override fun onSurfaceChanged(width: Int, height: Int) {

//        //设置透视投影
//        Matrix.frustumM(
//            mProjectMatrix, 0
//            , -ratio, ratio, -1f, 1f, 3f, 7f
//        )
//        //设置相机位置
//        Matrix.setLookAtM(
//            mViewMatrix, 0,
//            0f, 0f, 8.0f,   //eyeZ=7表示相机位置设置在目标正前方
//            0f, 0f, 0f,//目标的坐标
//
//            0.0f, 1.0f, 0.0f
//        )  //up为三个向量，合成的方向才是相机最终的方向，
//        //若（0，1，0）为正视目标，则（1，1，0）旋转了45°
//        //计算变换矩阵
//        Matrix.multiplyMM(
//            mMVPMatrix, 0,
//            mProjectMatrix, 0,
//            mViewMatrix, 0
//        )

        //计算宽高比

        val ratio = width.toFloat() / height
        //设置透视投影
        Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 20f)
        //设置相机位置
        Matrix.setLookAtM(
            mViewMatrix,
            0,
            1.0f,
            -10.0f,
            -4.0f,
            0f,
            0f,
            0f,
            0f,
            1.0f,
            0.0f
        )
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mViewMatrix, 0)

        circleDrawer.onSurfaceChanged(width, height)
    }

    override fun onDrawFrame() {

        GLES20.glUseProgram(mProgram)
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition")
        GLES20.glEnableVertexAttribArray(mPositionHandle)
        GLES20.glVertexAttribPointer(
            mPositionHandle,
            COORDS_PER_VERTEX,  //顶点数据个数
            GLES20.GL_FLOAT,
            false,
            vertexStride, //顶点占有的字节总数
            vertexBuffer
        )

        //给vMatrix赋值
        val mMatrixHandler = GLES20.glGetUniformLocation(mProgram, "vMatrix")
        GLES20.glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrix, 0)

        //给aColor赋值
//        val colorHandler = GLES20.glGetAttribLocation(mProgram, "aColor")
//        GLES20.glEnableVertexAttribArray(colorHandler)
//        GLES20.glVertexAttribPointer(
//            colorHandler, 4, GLES20.GL_FLOAT, false,
//            0, colorBuffer
//        )


        GLES20.glDrawArrays(
            GLES20.GL_TRIANGLE_FAN,
            0,
            triangleCoords!!.size / 3
        )  //如果用GL_TRIANGLE_FAN，三个点画一个扇形，第一个点为所有扇形圆心
//        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)  //如果用GL_TRIANGLE_STRIP，画两个三角形得传4个点，N个三角形N+2个点


        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle)
        circleDrawer.setMatrix(mMVPMatrix)
        circleDrawer.onDrawFrame()
    }

    override fun release() {
    }

}